/**
**********************************************************************
* @file     uart.c
* @brief    对文件的简要说明
* @details  对文件的详细说明
* @author   jcai
* @date     2022-05-18 20:24:02
* @copyright Copyright &copy; 2022 wy1107412334@163.com All rights reserved
* @version  v0.0.1
*
* \n Email:  wy1107412334@163.com
* \n Blog:   None
* \n Github: https://github.com/wy1107412334
* \n Gitee:  https://gitee.com/git.git1107412334.com
*
**********************************************************************
* @note
* None.
**********************************************************************
* @attention
* None.
**********************************************************************
@verbatim
@endverbatim
**********************************************************************
* @par 历史记录
* 1. v0.0.1: jcai, 2022-05-18 20:24:02
*   - 首次编写
* 2. v0.0.2: jcai, 2022-08-22 01:06:03
*   - 修复串口2，3的时钟启用错误
*   - 在没有注册串口接收钩子函数时，增加防止编译器优化掉读取串口接收
*     数据寄存器的语句
* 3. v0.0.3: jcai, 2022-08-27 15:53:08
*   - 修复串口中断优先级宏名错误
*   - 串口增加单字节数据发送函数
*
*<center>Copyright &copy; 2022 wy1107412334@163.com All rights reserved</center>
**********************************************************************
*/

/* 头文件导入区 --------------------------------------------------- */

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "public.h"
#include "uart.h"


/** @defgroup UART UART
* @brief uart modules
* @{
*/



/*********************************************************************
                私有宏定义
*********************************************************************/






/*********************************************************************
                私有数据类型声明
*********************************************************************/

#define UARTx_SEND_defined(dev_id)                                  \
    void Uart##dev_id##_send(uint8_t *buf, uint16_t len)            \
    {                                                               \
        while (len--)                                               \
        {                                                           \
            UART##dev_id##_DEV->DR = (uint16_t)*(buf++);            \
            while ((uint16_t)RESET ==                               \
                   (UART##dev_id##_DEV->SR & USART_FLAG_TXE)) ;     \
        }                                                           \
        while ((uint16_t)RESET ==                                   \
               (UART##dev_id##_DEV->SR & USART_FLAG_TC)) ;          \
    }

#define UARTx_SEND_BYTE_defined(dev_id)                             \
    void Uart##dev_id##_send_byte(uint16_t c)                       \
    {                                                               \
        UART##dev_id##_DEV->DR = c;                                 \
        while (!(UART##dev_id##_DEV->SR & USART_FLAG_TXE)) ;        \
    }

#define UARTx_RECV_BYTE_defined(dev_id)                             \
    void Uart##dev_id##_recv_byte(uint16_t c)                       \
    {                                                               \
        while (!(UART##dev_id##_DEV->SR & USART_FLAG_RXNE)) ;       \
        UART##dev_id##_DEV->DR = c;                                 \
    }




/*********************************************************************
                私有变量定义
*********************************************************************/

static USART_TypeDef *default_out = DEFAULT_STDOUT_DEV;

#ifdef UART1_EN
static uart_isr_t uart1_isr_hooks[UART_ISR_TYPE_NUM] = {0};
#endif
#ifdef UART2_EN
static uart_isr_t uart2_isr_hooks[UART_ISR_TYPE_NUM] = {0};
#endif
#ifdef UART3_EN
static uart_isr_t uart3_isr_hooks[UART_ISR_TYPE_NUM] = {0};
#endif




/** @defgroup UART_Exported_Variables uart exported variables
* @brief 全局变量定义
* @{
*/



/** defgroup UART_Exported_Variables
* @}
*/





/*********************************************************************
                私有函数定义
*********************************************************************/

#ifdef UART1_EN
void USART1_IRQHandler(void)
{
#ifdef UART1_IT_RX_EN
    if (USART_GetITStatus(UART1_DEV, USART_IT_ORE) == SET)
    {
        if (!!(UART1_DEV->DR | 0x8000) && uart1_isr_hooks[UART_ISR_ERROR])
            uart1_isr_hooks[UART_ISR_ERROR](UART1_DEV, USART_IT_ORE);
    }
    if (USART_GetITStatus(UART1_DEV, USART_IT_NE) == SET)
    {
        if (!!(UART1_DEV->DR | 0x8000) && uart1_isr_hooks[UART_ISR_ERROR])
            uart1_isr_hooks[UART_ISR_ERROR](UART1_DEV, USART_IT_NE);
    }
    if (USART_GetITStatus(UART1_DEV, USART_IT_FE) == SET)
    {
        if (!!(UART1_DEV->DR | 0x8000) && uart1_isr_hooks[UART_ISR_ERROR])
            uart1_isr_hooks[UART_ISR_ERROR](UART1_DEV, USART_IT_FE);
    }
    if (USART_GetITStatus(UART1_DEV, USART_IT_PE) == SET)
    {
        if (!!(UART1_DEV->DR | 0x8000) && uart1_isr_hooks[UART_ISR_ERROR])
            uart1_isr_hooks[UART_ISR_ERROR](UART1_DEV, USART_IT_PE);
    }
    if (USART_GetITStatus(UART1_DEV, USART_IT_RXNE) == SET)
    {
        uint16_t recv = UART1_DEV->DR;
        if (!!(recv | 0x8000) && uart1_isr_hooks[UART_ISR_RX])
            uart1_isr_hooks[UART_ISR_RX](UART1_DEV, recv);
    }
#endif

#ifdef UART1_IT_TX_EN
    if (USART_GetITStatus(UART1_DEV, USART_IT_TXE) == SET)
    {
        if (uart1_isr_hooks[UART_ISR_TX])
            uart1_isr_hooks[UART_ISR_TX](UART1_DEV, UART_ISR_TX);
    }
    if (USART_GetITStatus(UART1_DEV, USART_IT_TC) == SET)
    {
        if (uart1_isr_hooks[UART_ISR_TC])
            uart1_isr_hooks[UART_ISR_TC](UART1_DEV, UART_ISR_TC);
    }
#endif

#ifdef UART1_IT_IDLE_EN
    if (USART_GetITStatus(UART1_DEV, USART_IT_IDLE) == SET)
    {
        if (uart1_isr_hooks[UART_ISR_IDLE])
            uart1_isr_hooks[UART_ISR_IDLE](UART1_DEV, UART_ISR_IDLE);
    }
#endif
}

static void uart1_init(void)
{
    USART_InitTypeDef uart_init;
    GPIO_InitTypeDef  gpio_init;
#if defined(UART1_IT_RX_EN) || defined(UART1_IT_TX_EN) || \
    defined(UART1_IT_IDLE_EN)
    NVIC_InitTypeDef  nvic_init;
#endif

    RCC_APB2PeriphClockCmd(UART1_TX_GPIO_RCC | UART1_RX_GPIO_RCC |
                           RCC_APB2Periph_AFIO, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

    gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
    gpio_init.GPIO_Mode  = GPIO_Mode_AF_PP;
    gpio_init.GPIO_Pin   = UART1_TX_GPIO_PIN;
    GPIO_Init(UART1_TX_GPIO_PORT, &gpio_init);
    gpio_init.GPIO_Mode  = GPIO_Mode_IN_FLOATING;
    gpio_init.GPIO_Pin   = UART1_RX_GPIO_PIN;
    GPIO_Init(UART1_RX_GPIO_PORT, &gpio_init);
#if UART1_GPIO_PIN_REMAP
    GPIO_PinRemapConfig(GPIO_Remap_USART1, ENABLE);
#else
    GPIO_PinRemapConfig(GPIO_Remap_USART1, DISABLE);
#endif

    uart_init.USART_BaudRate            = UART1_DEV_BAUD_RATE;
    uart_init.USART_WordLength          = UART1_DEV_DATA_LENGTH;
    uart_init.USART_StopBits            = UART1_DEV_STOPBITS;
    uart_init.USART_Parity              = UART1_DEV_PARITY;
    uart_init.USART_Mode                = USART_Mode_Tx | USART_Mode_Rx;
    uart_init.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_Init(UART1_DEV, &uart_init);

#if defined(UART1_IT_RX_EN)
    USART_ClearFlg(UART1_DEV, USART_FLAG_RXNE);
    USART_ITConfig(UART1_DEV, USART_IT_RXNE, ENABLE);
#endif
#if defined(UART1_IT_TX_EN)
    USART_ClearFlg(UART1_DEV, USART_FLAG_TC);
    USART_ITConfig(UART1_DEV, USART_IT_TC, ENABLE);
    USART_ITConfig(UART1_DEV, USART_IT_TXE, ENABLE);
#endif
#if defined(UART1_IT_IDLE_EN)
    USART_ITConfig(UART1_DEV, USART_IT_IDLE, ENABLE);
#endif

#if defined(UART1_IT_RX_EN) || defined(UART1_IT_TX_EN) || \
    defined(UART1_IT_IDLE_EN)
    nvic_init.NVIC_IRQChannel                   = USART1_IRQn;
    nvic_init.NVIC_IRQChannelPreemptionPriority = UART1_ISR_MAINPRIO;
    nvic_init.NVIC_IRQChannelSubPriority        = UART1_ISR_SUBPRIO;
    nvic_init.NVIC_IRQChannelCmd                = ENABLE;
    NVIC_Init(&nvic_init);
#endif

    USART_Cmd (UART1_DEV, ENABLE);
}
#endif /* UART1_END */


#ifdef UART2_EN
void USART2_IRQHandler(void)
{
#ifdef UART2_IT_RX_EN
    if (USART_GetITStatus(UART2_DEV, USART_IT_ORE) == SET)
    {
        if (!!(UART2_DEV->DR | 0x8000) && uart2_isr_hooks[UART_ISR_ERROR])
            uart2_isr_hooks[UART_ISR_ERROR](UART2_DEV, USART_IT_ORE);
    }
    if (USART_GetITStatus(UART2_DEV, USART_IT_NE) == SET)
    {
        if (!!(UART2_DEV->DR | 0x8000) && uart2_isr_hooks[UART_ISR_ERROR])
            uart2_isr_hooks[UART_ISR_ERROR](UART2_DEV, USART_IT_NE);
    }
    if (USART_GetITStatus(UART2_DEV, USART_IT_FE) == SET)
    {
        if (!!(UART2_DEV->DR | 0x8000) && uart2_isr_hooks[UART_ISR_ERROR])
            uart2_isr_hooks[UART_ISR_ERROR](UART2_DEV, USART_IT_FE);
    }
    if (USART_GetITStatus(UART2_DEV, USART_IT_PE) == SET)
    {
        if (!!(UART2_DEV->DR | 0x8000) && uart2_isr_hooks[UART_ISR_ERROR])
            uart2_isr_hooks[UART_ISR_ERROR](UART2_DEV, USART_IT_PE);
    }
    if (USART_GetITStatus(UART2_DEV, USART_IT_RXNE) == SET)
    {
        uint16_t recv = UART2_DEV->DR;
        if (!!(recv | 0x8000) && uart2_isr_hooks[UART_ISR_RX])
            uart2_isr_hooks[UART_ISR_RX](UART2_DEV, recv);
    }
#endif

#ifdef UART2_IT_TX_EN
    if (USART_GetITStatus(UART2_DEV, USART_IT_TXE) == SET)
    {
        if (uart2_isr_hooks[UART_ISR_TX])
            uart2_isr_hooks[UART_ISR_TX](UART2_DEV, UART_ISR_TX);
    }
    if (USART_GetITStatus(UART2_DEV, USART_IT_TC) == SET)
    {
        if (uart2_isr_hooks[UART_ISR_TC])
            uart2_isr_hooks[UART_ISR_TC](UART2_DEV, UART_ISR_TC);
    }
#endif

#ifdef UART2_IT_IDLE_EN
    if (USART_GetITStatus(UART2_DEV, USART_IT_IDLE) == SET)
    {
        if (uart2_isr_hooks[UART_ISR_IDLE])
            uart2_isr_hooks[UART_ISR_IDLE](UART2_DEV, UART_ISR_IDLE);
    }
#endif
}

static void uart2_init(void)
{
    USART_InitTypeDef uart_init;
    GPIO_InitTypeDef  gpio_init;
#if defined(UART2_IT_RX_EN) || defined(UART2_IT_TX_EN) || \
    defined(UART2_IT_IDLE_EN)
    NVIC_InitTypeDef  nvic_init;
#endif

    RCC_APB2PeriphClockCmd(UART2_TX_GPIO_RCC | UART2_RX_GPIO_RCC |
                           RCC_APB2Periph_AFIO, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

    gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
    gpio_init.GPIO_Mode  = GPIO_Mode_AF_PP;
    gpio_init.GPIO_Pin   = UART2_TX_GPIO_PIN;
    GPIO_Init(UART2_TX_GPIO_PORT, &gpio_init);
    gpio_init.GPIO_Mode  = GPIO_Mode_IN_FLOATING;
    gpio_init.GPIO_Pin   = UART2_RX_GPIO_PIN;
    GPIO_Init(UART2_RX_GPIO_PORT, &gpio_init);
#if UART2_GPIO_PIN_REMAP
    GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE);
#else
    GPIO_PinRemapConfig(GPIO_Remap_USART2, DISABLE);
#endif

    uart_init.USART_BaudRate            = UART2_DEV_BAUD_RATE;
    uart_init.USART_WordLength          = UART2_DEV_DATA_LENGTH;
    uart_init.USART_StopBits            = UART2_DEV_STOPBITS;
    uart_init.USART_Parity              = UART2_DEV_PARITY;
    uart_init.USART_Mode                = USART_Mode_Tx | USART_Mode_Rx;
    uart_init.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_Init(UART2_DEV, &uart_init);

#if defined(UART2_IT_RX_EN)
    USART_ClearFlg(UART2_DEV, USART_FLAG_RXNE);
    USART_ITConfig(UART2_DEV, USART_IT_RXNE, ENABLE);
#endif
#if defined(UART2_IT_TX_EN)
    USART_ClearFlg(UART2_DEV, USART_FLAG_TC);
    USART_ITConfig(UART2_DEV, USART_IT_TC, ENABLE);
    USART_ITConfig(UART2_DEV, USART_IT_TXE, ENABLE);
#endif
#if defined(UART2_IT_IDLE_EN)
    USART_ITConfig(UART2_DEV, USART_IT_IDLE, ENABLE);
#endif

#if defined(UART2_IT_RX_EN) || defined(UART2_IT_TX_EN) || \
    defined(UART2_IT_IDLE_EN)
    nvic_init.NVIC_IRQChannel                   = USART2_IRQn;
    nvic_init.NVIC_IRQChannelPreemptionPriority = UART2_ISR_MAINPRIO;
    nvic_init.NVIC_IRQChannelSubPriority        = UART2_ISR_SUBPRIO;
    nvic_init.NVIC_IRQChannelCmd                = ENABLE;
    NVIC_Init(&nvic_init);
#endif

    USART_Cmd (UART2_DEV, ENABLE);
}
#endif /* UART2_END */


#ifdef UART3_EN
void USART3_IRQHandler(void)
{
#ifdef UART3_IT_RX_EN
    if (USART_GetITStatus(UART2_DEV, USART_IT_ORE) == SET)
    {
        if (!!(UART2_DEV->DR | 0x8000) && uar3_isr_hooks[UART_ISR_ERROR])
            uar3_isr_hooks[UART_ISR_ERROR](UART2_DEV, USART_IT_ORE);
    }
    if (USART_GetITStatus(UART2_DEV, USART_IT_NE) == SET)
    {
        if (!!(UART2_DEV->DR | 0x8000) && uar3_isr_hooks[UART_ISR_ERROR])
            uar3_isr_hooks[UART_ISR_ERROR](UART2_DEV, USART_IT_NE);
    }
    if (USART_GetITStatus(UART2_DEV, USART_IT_FE) == SET)
    {
        if (!!(UART2_DEV->DR | 0x8000) && uar3_isr_hooks[UART_ISR_ERROR])
            uar3_isr_hooks[UART_ISR_ERROR](UART2_DEV, USART_IT_FE);
    }
    if (USART_GetITStatus(UART2_DEV, USART_IT_PE) == SET)
    {
        if (!!(UART2_DEV->DR | 0x8000) && uar3_isr_hooks[UART_ISR_ERROR])
            uar3_isr_hooks[UART_ISR_ERROR](UART2_DEV, USART_IT_PE);
    }
    if (USART_GetITStatus(UART2_DEV, USART_IT_RXNE) == SET)
    {
        uint16_t recv = UART2_DEV->DR;
        if (!!(recv | 0x8000) && uar3_isr_hooks[UART_ISR_RX])
            uar3_isr_hooks[UART_ISR_RX](UART2_DEV, recv);
    }
#endif

#ifdef UART3_IT_TX_EN
    if (USART_GetITStatus(UART2_DEV, USART_IT_TXE) == SET)
    {
        if (uar3_isr_hooks[UART_ISR_TX])
            uar3_isr_hooks[UART_ISR_TX](UART2_DEV, UART_ISR_TX);
    }
    if (USART_GetITStatus(UART2_DEV, USART_IT_TC) == SET)
    {
        if (uar3_isr_hooks[UART_ISR_TC])
            uar3_isr_hooks[UART_ISR_TC](UART2_DEV, UART_ISR_TC);
    }
#endif

#ifdef UART3_IT_IDLE_EN
    if (USART_GetITStatus(UART2_DEV, USART_IT_IDLE) == SET)
    {
        if (uar3_isr_hooks[UART_ISR_IDLE])
            uar3_isr_hooks[UART_ISR_IDLE](UART2_DEV, UART_ISR_IDLE);
    }
#endif
}

static void uart3_init(void)
{
    USART_InitTypeDef uart_init;
    GPIO_InitTypeDef  gpio_init;
#if defined(UART3_IT_RX_EN) || defined(UART3_IT_TX_EN) || \
    defined(UART3_IT_IDLE_EN)
    NVIC_InitTypeDef  nvic_init;
#endif

    RCC_APB2PeriphClockCmd(UART3_TX_GPIO_RCC | UART3_RX_GPIO_RCC |
                           RCC_APB2Periph_AFIO, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);

    gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
    gpio_init.GPIO_Mode  = GPIO_Mode_AF_PP;
    gpio_init.GPIO_Pin   = UART3_TX_GPIO_PIN;
    GPIO_Init(UART3_TX_GPIO_PORT, &gpio_init);
    gpio_init.GPIO_Mode  = GPIO_Mode_IN_FLOATING;
    gpio_init.GPIO_Pin   = UART3_RX_GPIO_PIN;
    GPIO_Init(UART3_RX_GPIO_PORT, &gpio_init);
#if (UART3_GPIO_PIN_REMAP == 0)
    GPIO_PinRemapConfig(GPIO_FullRemap_USART3, DISABLE);
#elif (UART3_GPIO_PIN_REMAP == 1)
    GPIO_PinRemapConfig(GPIO_PartialRemap_USART3, ENABLE);
#elif (UART3_GPIO_PIN_REMAP == 2)
    GPIO_PinRemapConfig(GPIO_FullRemap_USART3, ENABLE);
#endif

    uart_init.USART_BaudRate            = UART3_DEV_BAUD_RATE;
    uart_init.USART_WordLength          = UART3_DEV_DATA_LENGTH;
    uart_init.USART_StopBits            = UART3_DEV_STOPBITS;
    uart_init.USART_Parity              = UART3_DEV_PARITY;
    uart_init.USART_Mode                = USART_Mode_Tx | USART_Mode_Rx;
    uart_init.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_Init(UART3_DEV, &uart_init);

#if defined(UART3_IT_RX_EN)
    USART_ClearFlg(UART3_DEV, USART_FLAG_RXNE);
    USART_ITConfig(UART3_DEV, USART_IT_RXNE, ENABLE);
#endif
#if defined(UART3_IT_TX_EN)
    USART_ClearFlg(UART3_DEV, USART_FLAG_TC);
    USART_ITConfig(UART3_DEV, USART_IT_TC, ENABLE);
    USART_ITConfig(UART3_DEV, USART_IT_TXE, ENABLE);
#endif
#if defined(UART3_IT_IDLE_EN)
    USART_ITConfig(UART3_DEV, USART_IT_IDLE, ENABLE);
#endif

#if defined(UART3_IT_RX_EN) || defined(UART3_IT_TX_EN) || \
    defined(UART3_IT_IDLE_EN)
    nvic_init.NVIC_IRQChannel                   = USART3_IRQn;
    nvic_init.NVIC_IRQChannelPreemptionPriority = UART3_ISR_MAINPRIO;
    nvic_init.NVIC_IRQChannelSubPriority        = UART3_ISR_SUBPRIO;
    nvic_init.NVIC_IRQChannelCmd                = ENABLE;
    NVIC_Init(&nvic_init);
#endif

    USART_Cmd (UART3_DEV, ENABLE);
}
#endif /* UART3_END */






/** @defgroup UART_Exported_Functions uart exported functions
* @brief 全局函数定义
* @{
*/



/**
**********************************************************************
* @brief    简要说明
* @details  详细说明
* @param    none
* @param[in]     a: 该参数用于输入
* @param[in,out] b: 该参数用于输入和输出
* @param[out]    c: 该参数用于输出
* @retval  none
* @retval  0 函数成功
* @retval  1 函数失败
* @return  返回0成功；否则失败
* @note    none
*/
void Uart_init(void)
{
#ifdef UART1_EN
    uart1_init();
#endif

#ifdef UART2_EN
    uart2_init();
#endif

#ifdef UART3_EN
    uart3_init();
#endif

    Uart_set_stdout(DEFAULT_STDOUT_DEV);
}
BSP_INIT_EXPORT(Uart_init);

void Uart_isr_register(USART_TypeDef * UARTx, uint8_t type, uart_isr_t fn)
{
    assert_param(type < UART_ISR_TYPE_NUM);

#ifdef UART1_EN
    if (UARTx == UART1_DEV)
    {
        uart1_isr_hooks[type] = fn;
        return;
    }
#endif
#ifdef UART2_EN
    if (UARTx == UART2_DEV)
    {
        uart2_isr_hooks[type] = fn;
        return;
    }
#endif
#ifdef UART3_EN
    if (UARTx == UART3_DEV)
    {
        uart3_isr_hooks[type] = fn;
        return;
    }
#endif

    assert_param(0);
}


#ifdef UART1_EN
UARTx_SEND_defined(1)
UARTx_SEND_BYTE_defined(1)
UARTx_RECV_BYTE_defined(1)
#endif

#ifdef UART2_EN
UARTx_SEND_defined(2)
UARTx_SEND_BYTE_defined(2)
UARTx_RECV_BYTE_defined(2)
#endif

#ifdef UART3_EN
UARTx_SEND_defined(3)
UARTx_SEND_BYTE_defined(3)
UARTx_RECV_BYTE_defined(3)
#endif

void Uart_set_stdout(USART_TypeDef *USARTx)
{
    assert_param(USARTx != NULL);
    default_out = USARTx;
}

void Uart_putc(uint16_t c)
{
    default_out->DR = c;
    while (!(default_out->SR & USART_FLAG_TXE)) ;
}
uint16_t Uart_getc(void)
{
    while (!(default_out->SR & USART_FLAG_RXNE)) ;
    return default_out->DR;
}


/** defgroup UART_Exported_Functions
* @}
*/

/** defgroup UART
* @}
*/


/***  Copyright (C) 2022 wy1107412334@163.com All rights reserved ***/
/****************************** END OF FILE *************************/

